using System;
using System.Collections.Generic;
using System.Text;

using Mud.Common;
using Mud.Common.Messages;
using Mud.Server.Physical;
using Mud.Server.Users;

namespace Mud.Server
{

	/// <summary>
	/// Represents the Mud game server.
	/// </summary>
	public interface  IServer
    {

        #region Properties

        /// <summary>
        /// Object which is responsible for generating Ids
        /// </summary>
		ObjectIdManager CurrentObjectIdManager
        {
            get;
        }

        /// <summary>
        /// Gets the command factory for creating command message handlers.
        /// </summary>
		MessageHandlerFactory<Client.Commands.ICommand> CurrentCommandFactory
        {
            get;
        }

        /// <summary>
        /// Current state of the server (statistics).
        /// </summary>
        ServerState CurrentServerState
        {
            get;
        }

        /// <summary>
        /// Server configuration settings.
        /// </summary>
        ServerConfiguration CurrentConfiguration
        {
            get;
        }

        /// <summary>
        /// Object loader.
        /// </summary>
		ObjectLoader CurrentObjectLoader
        {
            get;
        }

        /// <summary>
        /// List of currently connected clients.
        /// </summary>
		IReadOnlyCollection<Client.IClient> Clients
        {
            get;
        }

        /// <summary>
        /// This list contains methods with specific time index (miliseconds).
        /// When the server reaches this index (tick) it will execute the method.
        /// </summary>
		Scheduler CurrentScheduler
        {
            get;
        }

        /// <summary>
        /// Current time index (milliseconds) that the server is in. This is used primarily
        /// for CommandScheduler. 
        /// </summary>
        int CurrentTimeIndex
        {
            get;
        }

        /// <summary>
        /// StopFlag which can be used to stop the server.
        /// </summary>
        StopFlag ServerStopFlag
        {
            get;
        }

        #endregion

        #region Events

        /// <summary>
        /// Event raised when client connects.
        /// </summary>
        event EventHandler<ClientConnectedEventArgs> ClientConnected;

        /// <summary>
        /// Event raised when client disconnects.
        /// </summary>
        event EventHandler<ClientDisconnectedEventArgs> ClientDisconnected;

        /// <summary>
        /// Event raised when a player characters enters the game.
        /// </summary>
        event EventHandler<PlayerCharacterEnteredGameEventArgs> PlayerCharacterEnteredGame;

        /// <summary>
        /// Event raised when a player characters exits the game.
        /// </summary>
        event EventHandler<PlayerCharacterExitedGameEventArgs> PlayerCharacterExitedGame;

        /// <summary>
        /// Event raised when the server is stoping.
        /// </summary>
        event EventHandler ServerStopping;

        #endregion

        #region Server commands

        /// <summary>
        /// Sends a message to all clients.
        /// </summary>
        /// <param name="sender">Message sender.</param>
        /// <param name="message">Message to send.</param>
		ResultWithReason BroadcastMessage(string sender, string message);

        /// <summary>
        /// Places the character in the game world. If this method fails for any reason
        /// then the returning message will have description why it has failed.
        /// </summary>
        /// <param name="creature">The character to place.</param>
        /// <param name="areaName">Name of the area where the character is located.</param>
		ResultWithReason EnterGame(Creature creature, string areaName);

        /// <summary>
        /// Removes the character in the game world. If this method fails for any reason
        /// then the returning message will have description why it has failed.
        /// </summary>
        /// <param name="creature">The character to remove.</param>
		ResultWithReason ExitGame(Creature creature);

        /// <summary>
        /// Gets the area with specific name.
        /// </summary>
        /// <param name="areaName">Area name.</param>
        /// <returns>Area.</returns>
        Area GetArea(string areaName);

		/// <summary>
		/// Adds a new client to the server. 
		/// This method is tread safe.
		/// </summary>
		/// <param name="client">Client to add.</param>
		ResultWithReason AddClient(Client.IClient client);

		/// <summary>
		/// Requests that the client be removed from the server.
		/// This method is tread safe.
		/// </summary>
		/// <param name="client">Client to remove.</param>
		ResultWithReason RequestRemoveClient(Client.IClient client);

        #endregion
 
	}
}
